/**
 * 全局状态管理
 */

import MapEditor from '../mapClass/index';
import currentSprite from '../mapClass/currentSprite';
import { getMaxRectFN } from '../utils/getMaxRect';
import {
    spriteList,
    zSprite,
    sSprite,
    lSprite,
    jSprite,
    oSprite,
    iSprite,
    tSprite,
} from './spriteIIcon';

export interface mapConstDS {
    editor: MapEditor;
}

export class MapConst {
    /**
     * editor
     */
    public editor: MapEditor | undefined = undefined;

    /**
     * 游戏开始位置
     */
    public pW = 0;  // 页面宽
    public pH = 0;
    public sW = 9;  // 游戏区域比例
    public sH = 16;
    public gX = 0;  // 游戏区域 位置
    public gY = 0;
    public gW = 0;  // 游戏区域 尺寸
    public gH = 0;
    public rectsize = 0; // 块尺寸

    public gridW = 20;
    public gridH = 25;
    public gridPW = 26; // 横向格子数量

    /**
     * 积分
     */
    public integral = 0;

    /**
     * 所有格子的显示
     */
    public gridIconList: {
        value: number,
        rect: any,
    }[][] = [];

    /**
     * 下一个格子数据
     */
    public nextSpriteData: {
        type: string;
        sprite: number[][][];
        index: number;
    } = this.getNextRectFN();


    /**
     * 当前格子
     */
    public spriteThis: currentSprite | undefined;
    public spriteData: {
        type: string;
        sprite: number[][][];
        index: number;
    } = this.getNextRectFN();
    public stepX: number | undefined = undefined;   // 当前格子xy位置
    public stepY: number | undefined = undefined;
    public moveStart = new Date().getTime();
    public moveTime = 300;

    /**
     * 播放状态:
     * 0 - 开始游戏
     * 1 - 游戏中
     * 2 - 游戏暂停
     * 3 - 游戏结束
     */
    public isPause = 0;
    public isPauseLabel = '开始游戏'; // 播放状态标语

    /**
     * 计算尺寸
     */
    public setGameSizeFS(pWidth: number, pHeight: number) {
        return new Promise<void>(resolve => {

            /**
             * 页面宽
             */
            this.pW = pWidth;
            this.pH = pHeight;

            getMaxRectFN(
                this.sW,
                this.sH,
                this.pW - 10,
                this.pH - 10
            ).then((result) => {

                /**
                 * 游戏区域 尺寸
                 */
                const rectsizeW = Math.floor(result.width / this.gridPW); // 块尺寸
                this.rectsize = rectsizeW; // 块尺寸
                this.gW = result.width;
                this.gH = result.height;

                /**
                 * 游戏区域 位置
                 */
                this.gX = (pWidth - this.gW) / 2;
                this.gY = (pHeight - this.gH) / 2;
                resolve();
            });
        });
    }

    /**
     * 设置 editor
     * @param editor 主对像
     */
    public setEditorFN(editor: MapEditor) {
        this.editor = editor;
    }

    public gamePlay() {
        this.spriteMove();
        this.gridIconListFN();
    }
    /**
     * sprite垂直移动
     */
    public spriteMove() {
        const time = new Date().getTime() - this.moveStart;
        if (time < this.moveTime || this.isPause != 1) return;
        this.moveStart = new Date().getTime();
        const stepY = (this.stepY || 0) + 1;
        this.spriteThis && this.spriteThis.moveSprite();

        const spriteData = this.spriteData.sprite[this.spriteData.index];
        const gridY = stepY + spriteData.length;
        const currentLine = this.gridIconList[gridY - 1];
        if (currentLine) {
            let judgeMove = true;
            for (let index = 0; index < spriteData.length; index++) {
                const element = spriteData[index];
                const elementG = this.gridIconList[stepY + index];
                if(elementG){
                    for (let indexE = 0; indexE < element.length; indexE++) {
                        const elementE = element[indexE];
                        const gridItem = elementG[(this.stepX || 0) + indexE];
                        if (elementE == 1 && gridItem.value === 1) {
                            judgeMove = false;
                            break;
                        }
                    }
                    if (!judgeMove) break;
                }
                if (!judgeMove) break;
            }
            judgeMove && (this.stepY = stepY);
            !judgeMove && this.spriteMoveEnd();
        } else {
            this.spriteMoveEnd();
        }
    }
    /**
     * sprite横向移动
     */
    public spriteMoveTransverseFN(num:number){
        return new Promise<void>(resolve => {
            const stepX = (this.stepX || 0) + num;
            const stepY = (this.stepY || 0);
            const spriteData = this.spriteData.sprite[this.spriteData.index];

            if (stepX >= 0 && stepX <= (this.gridW - spriteData[0].length)) {
                const gridY = (stepY || 0) + spriteData.length;
                const currentLine = this.gridIconList[gridY - 1];
                if (currentLine) {
                    let judgeMove = true;
                    for (let index = 0; index < spriteData.length; index++) {
                        const element = spriteData[index];
                        const elementG = this.gridIconList[stepY + index];
                        if(elementG){
                            for (let indexE = 0; indexE < element.length; indexE++) {
                                const elementE = element[indexE];
                                const gridItem = elementG[(stepX || 0) + indexE];
                                if (elementE == 1 && gridItem.value === 1) {
                                    judgeMove = false;
                                    break;
                                }
                            }
                            if (!judgeMove) break;
                        }
                        if (!judgeMove) break;
                    }
                    judgeMove && (this.stepX = stepX);
                    judgeMove && this.spriteThis?.canvas.x((this.stepX || 0) * this.rectsize);
                }
                resolve();
            }else{
                resolve();
            }
        });
    }
    /**
     * 移动结束
     */
    public spriteMoveEnd(){
        let judgeEnd = true;
        const spriteData = this.spriteData.sprite[this.spriteData.index];
        for (let index = 0; index < spriteData.length; index++) {
            const element = spriteData[index];
            const elementG = this.gridIconList[(this.stepY || 0) + index];
            if(elementG){
                for (let indexE = 0; indexE < element.length; indexE++) {
                    const elementE = element[indexE];
                    const gridItem = elementG[(this.stepX || 0) + indexE];
                    if (elementE == 1) {
                        gridItem.value = 1;
                        gridItem.rect.fill('#dddddd');
                    }
                }
            }else{
                judgeEnd = false;
                break;
            }
        }
        judgeEnd && this.spriteThis?.initSpriteFN();
        !judgeEnd && this.gameOver();
    }
    /**
     * 积分计算
     */
    public integralFN(){
        for (let index = 0; index < this.gridIconList.length; index++) {
            const element = this.gridIconList[index];
            let judgeIntegral = true;
            for (let indexI = 0; indexI < element.length; indexI++) {
                const elementI = element[indexI];
                if(elementI.value === 0){
                    judgeIntegral = false;
                    break;
                }
            }
            if(judgeIntegral){
                this.integral+=1;
                this.editor?.gameComp?.integralCanvas.text(this.integral);
                for (let indexI = 0; indexI < index; indexI++) {
                    const indexThis = index - indexI;
                    const elementI = this.gridIconList[indexThis];
                    const nextElementI = this.gridIconList[indexThis - 1];
                    if(nextElementI && elementI){
                        elementI.forEach((item, itemIndex) => {
                            item.value = nextElementI[itemIndex].value;
                            item.rect.fill(item.value === 1 ? '#dddddd' : '#000000');
                        });
                    }else{
                        elementI.forEach((item) => {
                            item.value = 0;
                            item.rect.fill('#000000');
                        });
                    }
                }
            }
        }
    }
    /**
     * 格子变色等
     */
    public gridIconListFN() {
        const gridIconListLenth = this.gridIconList.length;
        for (let index = 0; index < gridIconListLenth; index++) {
            const eleIndex = gridIconListLenth - index - 1;
            const element = this.gridIconList[eleIndex];
            for (let indexE = 0; indexE < element.length; indexE++) {
                const elementE = element[indexE];
                if (elementE.value === 1) {
                    elementE.rect.fill('#dddddd');
                } else {
                    elementE.rect.fill('#000000');
                }
            }
        }
    }
    /**
     * 获取下一个形状
     */
    public getNextRectFN() {
        const icon = this.getrandFN(0, spriteList.length - 1);
        let sprite: number[][][] = [];
        switch (icon) {
            case 0:
                sprite = zSprite;
                break;
            case 1:
                sprite = sSprite;
                break;
            case 2:
                sprite = lSprite;
                break;
            case 3:
                sprite = jSprite;
                break;
            case 4:
                sprite = oSprite;
                break;
            case 5:
                sprite = iSprite;
                break;
            case 6:
                sprite = tSprite;
                break;
        }
        return {
            type: spriteList[icon],
            sprite,
            index: this.getrandFN(0, sprite.length - 1)
        };
    }
    /**
     * 游戏结束
     */
    public gameOver(){
        this.isPause = 3;
        this.isPauseLabel = '游戏结束！';
    }
    /**
     * 获取随机整数
     */
    public getrandFN(m: number, n: number) {
        return Math.floor(Math.random() * (n - m + 1)) + m; //#核心代码
    }
    /**
     * 元素变换
     */
    public changeSpriteFN(){
        const index =  this.spriteData.index;
        const sprite = this.spriteData.sprite;
        sprite.forEach((item, itemIndex)=>{
            if(index === itemIndex){
                if(index != (sprite.length - 1)){
                    this.spriteData.index+=1;
                }else{
                    this.spriteData.index = 0;
                }
            }
        });
        this.spriteThis?.drawSpriteFN();
    }
    /**
     * 设置事件
     */
    public settingEventFN(node:any, event: ()=>void){
        node.on('click', () => {
            event();
        });
        node.on('tap', () => {
            event();
        });
    }
}

export const mapConst: MapConst = new MapConst();
